// IndexedDB工具类
const DB_NAME = 'excelCompareDB'
const DB_VERSION = 2

// 存储名称常量
const STORE_NAMES = {
  EXCEL2_DATA: 'excel2Data', // 存储Excel2的数据
  COMPARE_RESULTS: 'compareResults', // 存储比较结果
}

interface Excel2Record {
  id: string // 根据比较列生成的唯一ID
  rowData: any[] // 行数据
  rowIndex: number // 行号
}

interface CompareResult {
  id: string // 自增ID
  type: 'different' | 'only-in-file1' | 'only-in-file2'
  excel1Data: any[] // Excel1的行数据
  excel2Data: any[] // Excel2的行数据
  rowNum1?: number // Excel1的行号
  rowNum2?: number // Excel2的行号
  differences?: Array<{
    columnName: string
    value1: any
    value2: any
  }> // 差异详情
}

class IndexedDBUtil {
  private db: IDBDatabase | null = null

  // 初始化数据库
  async initDB(): Promise<void> {
    return new Promise((resolve, reject) => {
      console.log('开始初始化数据库')
      const request = indexedDB.open(DB_NAME, DB_VERSION)

      request.onerror = () => {
        console.log('数据库打开失败')
        reject(new Error('数据库打开失败'))
      }

      request.onsuccess = async (event) => {
        console.log('数据库打开成功')
        this.db = (event.target as IDBOpenDBRequest).result
        // 如果数据库已存在，清空所有store中的数据
        try {
          const stores = Array.from(this.db.objectStoreNames)
          if (stores.length > 0) {
            console.log('数据库已存在，清空所有数据')
            const transaction = this.db.transaction(stores, 'readwrite')

            await Promise.all(
              stores.map((storeName) => {
                return new Promise<void>((resolve, reject) => {
                  console.log(`清空store: ${storeName}`)
                  const store = transaction.objectStore(storeName)
                  const clearRequest = store.clear()

                  clearRequest.onsuccess = () => {
                    console.log(`${storeName} 清空成功`)
                    resolve()
                  }

                  clearRequest.onerror = () => {
                    console.error(`清空 ${storeName} 失败`)
                    reject(new Error(`清空 ${storeName} 失败`))
                  }
                })
              }),
            )

            console.log('所有store清空完成')
          }
        } catch (error) {
          console.error('清空数据库失败:', error)
        }

        resolve()
      }

      request.onupgradeneeded = (event) => {
        console.log('数据库版本更新')
        const db = (event.target as IDBOpenDBRequest).result

        // 创建Excel2数据存储
        if (!db.objectStoreNames.contains(STORE_NAMES.EXCEL2_DATA)) {
          console.log('创建excel2数据存储')
          db.createObjectStore(STORE_NAMES.EXCEL2_DATA, { keyPath: 'id' })
        }

        // 创建比较结果存储
        if (!db.objectStoreNames.contains(STORE_NAMES.COMPARE_RESULTS)) {
          console.log('创建比较结果存储')
          const store = db.createObjectStore(STORE_NAMES.COMPARE_RESULTS, {
            keyPath: 'id',
            autoIncrement: true,
          })
          // 添加索引以便于查询
          store.createIndex('type', 'type', { unique: false })
        }
      }
    })
  }

  // 清空所有数据
  async clearAllData(): Promise<void> {
    console.log('clearAllData')
    if (!this.db) {
      console.log('开始初始化db')
      await this.initDB()
      console.log('初始化结束')
      return // 因为initDB中已经包含了清空数据的逻辑
    }

    return new Promise((resolve, reject) => {
      try {
        const stores = Array.from(this.db!.objectStoreNames)
        if (stores.length === 0) {
          console.log('没有需要清空的store')
          resolve()
          return
        }

        let completed = 0
        stores.forEach((storeName) => {
          console.log(`清空store: ${storeName}`)
          const transaction = this.db!.transaction(storeName, 'readwrite')
          const store = transaction.objectStore(storeName)
          const request = store.clear()

          request.onsuccess = () => {
            console.log(`${storeName} 清空成功`)
            completed++
            if (completed === stores.length) {
              console.log('所有store清空完成')
              resolve()
            }
          }

          request.onerror = () => {
            console.error(`清空 ${storeName} 失败`)
            reject(new Error(`清空 ${storeName} 失败`))
          }
        })
      } catch (error) {
        reject(error)
      }
    })
  }

  // 保存Excel2的一行数据
  async saveExcel2Row(record: Excel2Record): Promise<void> {
    if (!this.db) {
      await this.initDB()
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAMES.EXCEL2_DATA], 'readwrite')
      const store = transaction.objectStore(STORE_NAMES.EXCEL2_DATA)

      const request = store.put(record)

      request.onsuccess = () => resolve()
      request.onerror = () => reject(new Error('保存Excel2数据行失败'))
    })
  }

  // 根据ID查找Excel2的数据
  async findExcel2RowById(id: string): Promise<Excel2Record | null> {
    if (!this.db) {
      await this.initDB()
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAMES.EXCEL2_DATA], 'readonly')
      const store = transaction.objectStore(STORE_NAMES.EXCEL2_DATA)

      const request = store.get(id)

      request.onsuccess = () => resolve(request.result || null)
      request.onerror = () => reject(new Error('查询Excel2数据失败'))
    })
  }

  // 保存比较结果
  async saveCompareResult(result: Omit<CompareResult, 'id'>): Promise<void> {
    if (!this.db) {
      await this.initDB()
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAMES.COMPARE_RESULTS], 'readwrite')
      const store = transaction.objectStore(STORE_NAMES.COMPARE_RESULTS)

      const request = store.add(result)

      request.onsuccess = () => resolve()
      request.onerror = () => reject(new Error('保存比较结果失败'))
    })
  }

  // 获取所有比较结果
  async getAllCompareResults(): Promise<CompareResult[]> {
    if (!this.db) {
      await this.initDB()
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([STORE_NAMES.COMPARE_RESULTS], 'readonly')
      const store = transaction.objectStore(STORE_NAMES.COMPARE_RESULTS)

      const request = store.getAll()

      request.onsuccess = () => resolve(request.result)
      request.onerror = () => reject(new Error('获取比较结果失败'))
    })
  }
}

export const indexedDBUtil = new IndexedDBUtil()
